<template>
  <el-dialog class="bs-dialog" 
    :model-value="modelValue"
    @update:model-value="handleUpdateModalValue"
    :draggable="draggable"
    :append-to-body="appendToBody"
    :close-on-click-modal="closeOnClickModal"
    :close-on-press-escape="closeOnPressEscape"
    :align-center="alignCenter"
    v-bind="$attrs"
  >
    <template #header="{close, titleId, titleClass}">
      <div ref="headerRef">
        <slot name="header" :close="close" :titleId="titleId" :titleClass="titleClass">
          <div class="title-text">{{ title }}</div>
        </slot>
      </div>
    </template>
    <!--内容区域-->
    <div :style="{height: computedBHeight}">
      <el-scrollbar>
        <div ref="bodyRef">
          <slot></slot>
        </div>
      </el-scrollbar>
    </div>
    <template v-if="showFooter" #footer>
      <div ref='footerRef'>
        <slot name="footer">
          <div class="dialog-footer">
            <el-button size="large" @click="handleCancel()" v-if="cancelBtnVisible">{{ cancelBtnText }}</el-button>
            <el-button size="large" type="primary" @click="handleConfirm()" v-if="confirmBtnVisible">{{ confirmBtnText }}</el-button>
          </div>
        </slot>
      </div>
    </template>
  </el-dialog>
</template>
<script setup lang="ts">
import {ref, watch, nextTick, computed} from 'vue'

const emit = defineEmits(['update:model-value'])

type BsDialogProps = {
  modelValue: boolean
  title?: string
  appendToBody?: boolean
  draggable?: boolean
  alignCenter?: boolean
  closeOnClickModal?: boolean
  closeOnPressEscape?: boolean
  /**是否显示取消按钮 */
  cancelBtnVisible?: boolean
  /**取消按钮文案 */
  cancelBtnText?: string
  /**取消按钮点击逻辑处理 */
  cancelBtnFn?: () => any
  /**是否显示确定按钮 */
  confirmBtnVisible?: boolean
  /**确定按钮文案 */
  confirmBtnText?: string
  /**确定按钮点击逻辑处理 */
  confirmBtnFn?: () => any
  /** 是否显示底部 */
  showFooter?: boolean
  /***弹框内容区域高度 */
  bodyHeight?: number
}

const props = withDefaults(defineProps<BsDialogProps>(), {
  modelValue: false,
  title: '',
  appendToBody: true,
  draggable: true,
  alignCenter: true,
  closeOnClickModal: false,
  closeOnPressEscape: false,
  cancelBtnVisible: true,
  confirmBtnVisible: true,
  cancelBtnText: '取消',
  confirmBtnText: '确定',
  showFooter: true
})

const footerRef = ref()
const bodyRef = ref()
const headerRef = ref()
const bHeight = ref()

const handleUpdateModalValue = (value: boolean) => {
  emit('update:model-value', value)
}


/**
 * 点击取消事件处理
 */
const handleCancel = async () => {
  if (props.cancelBtnFn) {
    try {
      await props.cancelBtnFn()
      emit('update:model-value', false)
    } catch (e) {
    }
  } else {
    emit('update:model-value', false)
  }
}

/**
 * 点击确定事件处理
 */
const handleConfirm = async () => {
  if (props.confirmBtnFn) {
    try {
      const res = await props.confirmBtnFn()
      if (res !== false) {
        emit('update:model-value', false)
      }
    } catch (e) {
    }
  } else {
    emit('update:model-value', false)
  }
}

const computedBodyHeight = () => {
  let h = 0
  let f = 0
  let b = 0
  if (headerRef.value) {
    h = headerRef.value.parentNode.offsetHeight
  }
  if (footerRef.value) {
    f = footerRef.value.parentNode.offsetHeight
  }
  if (bodyRef.value) {
    b = bodyRef.value.offsetHeight
  }
  const maxH = window.innerHeight - (48 + h + f)
  if (b > maxH) {
    bHeight.value = maxH
  } else {
    bHeight.value = 0
  }
}
const computedBHeight = computed(() => {
  if (props.bodyHeight) {
    return props.bodyHeight + 'px'
  }
  if (bHeight.value) {
    return bHeight.value + 'px'
  }
  return ''
})

const config = { attributes: true, childList: true, subtree: true }
const observer = new MutationObserver(() => {
  computedBodyHeight()
})
watch(() => props.modelValue, () => {
  if (props.modelValue) {
    nextTick(() => {
      computedBodyHeight()
      observer.observe(bodyRef.value, config)
    })
  } else {
    observer.disconnect()
  }
})
</script>
<style lang="scss">
.bs-dialog {
  padding: 0;
  .el-dialog__header {
    line-height: 24px;
    padding: 12px 16px;
    border-bottom: solid 1px var(--border-color);
    .title-text {
      min-height: 24px;
      font-size: 16px;
      font-weight: 500;
      padding-right: 30px;
    }
    .el-dialog__headerbtn {
      top: 2px;
      height: 46px;
    }
  }
  .el-dialog__footer {
    padding-top: 0 !important;
  }
  .dialog-footer {
    padding: 24px;
    padding-top: 0;
    .el-button {
      min-width: 76px;
    }
    .el-button+.el-button {
      margin-left: 16px;
    }
  }
}
</style>